
package com.kugou.game.sdk.observers;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;

import com.kugou.game.sdk.entity.Message;
import com.kugou.game.sdk.entity.SmsColumns;
import com.kugou.game.sdk.entity.SmsMessage;
import com.kugou.game.sdk.observers.BaseContentObserver.OnContentChangeListener;

public class SmsMonitor implements OnContentChangeListener {

    /**
     * 获取短信验证码超时
     */
    private final int MSG_TIMEOUT = 1;

    private SmsMonitor mInstance;

    private String authCode;

    private onGetAuthCodeListener listener;

    private Context mContext;

    /**
     * 是否已经监听到验证码
     */
    private boolean hasGetAuthCode = false;

    protected Handler mUiHandler = new UiHandler(this);

    private static class UiHandler extends Handler {
        private final WeakReference<SmsMonitor> smsMonitor;

        public UiHandler(SmsMonitor monitor) {
            smsMonitor = new WeakReference<SmsMonitor>(monitor);
        }

        public void handleMessage(android.os.Message msg) {
            super.handleMessage(msg);
            if (smsMonitor.get() != null) {
                smsMonitor.get().handleUiMessage(msg);
            }
        };
    }

    /**
     * 处理更新UI任务
     * 
     * @param msg
     */
    public void handleUiMessage(android.os.Message msg) {
        switch (msg.what) {
            case MSG_TIMEOUT:
                handleFailed(ErrorCode.TIME_OUT);
                break;
            default:
                break;
        }

    }

    // public static synchronized SmsMonitor getInstance() {
    // if (mInstance == null) {
    // mInstance = new SmsMonitor();
    // }
    // return mInstance;
    // }

    public SmsMonitor(Context context) {
        mContext = context;
        mInstance = this;
    }

    /**
     * 自动获取验证码
     * 
     * @param monitorDuration 监听时间 单位：毫秒
     * @param listener 回调接口
     */
    public void getAuthCode(int monitorDuration, onGetAuthCodeListener listener) {
        hasGetAuthCode = false;
        this.listener = listener;
        mUiHandler.sendEmptyMessageDelayed(MSG_TIMEOUT, monitorDuration);
        registerReceiver();
        MessagesObserver.getObserver().addOnContentChangeListener(this);
    }

    @Override
    public void onContentChange(int whoObserver) {
        if (whoObserver != BaseContentObserver.MESSAGE_DB_OBSERVER) {
            return;
        }
        SmsMessage smsMessage = getLastSmsInboxMessage();
        if (isAuthCode(smsMessage)) {
            // 如果是我们的验证码信息，使用handler发送请求回调接口
            handleSuccess();
        }
    }

    /**
     * 是否是我们的验证短信
     * 
     * @param smsMessage
     * @return
     */
    private boolean isAuthCode(SmsMessage smsMessage) {
        if (hasGetAuthCode || smsMessage == null || TextUtils.isEmpty(smsMessage.getBody())) {
            return false;
        }
        // String s =
        // "您好，您的验证码是：034678，本条短信10分钟内有效：123456，如非本人操作请忽略。【酷狗游戏-手机注册】";
        // String body = s;

        String body = smsMessage.getBody();
        // 模拟错误信息
        // body = "abcdefg。【酷狗游戏-手机注册】";
        // 4.1.0之前【酷狗游戏-手机注册】
        // 4.1.0之后[手机注册]
        String regEx1 = "[手机注册]";
        String regEx2 = "[：]\\d+";
        Pattern pattern = Pattern.compile(regEx2);
        Matcher matcher = pattern.matcher(body);
        boolean flag = matcher.find();
        if (body.contains(regEx1) && flag) {
            authCode = matcher.group(0).replace("：", "");
            hasGetAuthCode = true;
            return true;
        } else if (body.contains(regEx1) && !flag) {
            handleFailed(ErrorCode.PARSE_ERROR);
            return false;
        }
        return false;
    }

    /**
     * 获取刚收到的短信
     * 
     * @return
     */
    private SmsMessage getLastSmsInboxMessage() {
        Message mdo = null;
        Cursor cursor = null;
        try {
            cursor = mContext.getContentResolver().query(
                    Uri.parse("content://sms/inbox"),
                    new String[] {
                            SmsColumns._ID, SmsColumns.THREAD_ID, SmsColumns.ADDRESS,
                            SmsColumns.DATE, SmsColumns.TYPE, SmsColumns.BODY, SmsColumns.STATUS,
                            SmsColumns.READ + " from sms where type=1 order by _id desc limit 1 --"
                    }, null, null, null);

            List<Message> list = mappingSmsMessage(cursor);
            if (!list.isEmpty()) {
                mdo = list.get(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeCursor(cursor);
        }
        return (SmsMessage) mdo;
    }

    /**
     * @param cursor
     * @return
     */
    private ArrayList<Message> mappingSmsMessage(Cursor cursor) {
        ArrayList<Message> smsList = new ArrayList<Message>();

        while (cursor != null && cursor.moveToNext()) {
            try {
                int sms_id = cursor.getInt(cursor.getColumnIndexOrThrow(SmsColumns._ID));
                int sms_thread_id = cursor.getInt(cursor
                        .getColumnIndexOrThrow(SmsColumns.THREAD_ID));
                String sms_address = cursor.getString(cursor
                        .getColumnIndexOrThrow(SmsColumns.ADDRESS));
                String sms_body = cursor.getString(cursor.getColumnIndexOrThrow(SmsColumns.BODY));
                Long sms_date = cursor.getLong(cursor.getColumnIndexOrThrow(SmsColumns.DATE));
                int sms_type = cursor.getInt(cursor.getColumnIndexOrThrow(SmsColumns.TYPE));
                int sms_status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsColumns.STATUS));
                int sms_read = cursor.getInt(cursor.getColumnIndexOrThrow(SmsColumns.READ));
                SmsMessage mdo = new SmsMessage();
                mdo.setBody(sms_body);
                mdo.setStatus(sms_status);
                mdo.setBoxType(sms_type);
                mdo.setId(sms_id);
                mdo.setThreadId(sms_thread_id);
                mdo.setDate(new Date(sms_date));
                if (mdo.getBoxType() >= SmsColumns.MESSAGE_TYPE_SENT) {
                    mdo.setTo(sms_address.trim());
                } else {
                    mdo.setFrom(sms_address.trim());
                }
                mdo.setRead(sms_read);
                smsList.add(mdo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        closeCursor(cursor);
        return smsList;
    }

    /**
     * 关闭数据库连接
     * 
     * @param c
     */
    public void closeCursor(Cursor c) {
        if (c != null) {
            try {
                c.close();
                c = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 描述:获取短信验证码回调接口
     * 
     * @author ljc
     * @since 2014-3-26 下午3:26:58
     */
    public interface onGetAuthCodeListener {
        /**
         * 获取短信验证码成功
         * 
         * @param authCode 短信验证码
         */
        public void onSuccess(String authCode);

        /**
         * 获取短信验证码超时
         * 
         * @param errorCode 错误码，1=获取短信超时 ，2=解析短信出错；更多请看{@link ErrorCode}
         */
        public void onFailed(int errorCode);
    }

    private SmsMonitorReceiver smsMonitorReceiver;

    private void registerReceiver() {
        smsMonitorReceiver = new SmsMonitorReceiver();
        IntentFilter smsFilter = new IntentFilter();
        smsFilter.addAction(SmsMonitorReceiver.Action);
        smsFilter.setPriority(2147483647);
        mContext.registerReceiver(smsMonitorReceiver, smsFilter);
    }

    private class SmsMonitorReceiver extends BroadcastReceiver {

        public final static String Action = "android.provider.Telephony.SMS_RECEIVED";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (!intent.getAction().equals(Action)) {
                return;
            }
            if (hasGetAuthCode) {
                return;
            }

            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                android.telephony.SmsMessage[] smsMessages = null;
                String fromNumber = null;
                Object[] myOBJpdus = (Object[]) bundle.get("pdus");
                smsMessages = new android.telephony.SmsMessage[myOBJpdus.length];
                StringBuilder body = new StringBuilder();
                for (int i = 0; i < myOBJpdus.length; i++) {
                    smsMessages[i] = android.telephony.SmsMessage
                            .createFromPdu((byte[]) myOBJpdus[i]);
                    fromNumber = smsMessages[i].getDisplayOriginatingAddress();
                    body.append(smsMessages[i].getDisplayMessageBody());
                }

                String num = fromNumber;
                Pattern pattern = Pattern.compile("^((\\+86)|(12520))");
                num = pattern.matcher(num).replaceAll("");

                SmsMessage smsMessage = new SmsMessage();
                smsMessage.setBody(body.toString());
                smsMessage.setFrom(fromNumber);

                // 广播监听到短信
                if (isAuthCode(smsMessage)) {
                    // 如果是我们的验证码信息，使用handler发送请求回调接口
                    handleSuccess();
                }
            }

        }
    }

    boolean hasUnRegister = false;

    /**
     * 成功获取短信验证码
     */
    public void handleSuccess() {
        unregisterMonitor();
        if (listener != null) {
            listener.onSuccess(authCode);
        }
    }

    /**
     * 取消所有监听，在Activity的onDestory记得调用
     */
    public void unregisterMonitor() {
        if (hasUnRegister) {
            return;
        }
        hasUnRegister = true;
        mUiHandler.removeMessages(MSG_TIMEOUT);
        MessagesObserver.getObserver().removeOnContentChangeListener(mInstance);
        mContext.unregisterReceiver(smsMonitorReceiver);
    }

    /**
     * 处理失败情况
     * 
     * @param errorCode 错误码，1=获取短信超时 ，2=解析短信出错；更多请看{@link ErrorCode}
     */
    public void handleFailed(int errorCode) {
        unregisterMonitor();
        if (listener != null) {
            listener.onFailed(errorCode);
        }
    }

    public class ErrorCode {
        /** 获取短信超时 */
        public final static int TIME_OUT = 1;

        /** 解析短信出错 */
        public final static int PARSE_ERROR = 2;
    }
}
